package com.linkgie.galaxyframework.httpproxy.converters;

import com.linkgie.galaxyframework.httpproxy.HttpRedirectException;
import com.linkgie.galaxyframework.httpproxy.HttpRequestException;
import com.linkgie.galaxyframework.httpproxy.HttpStatusException;
import com.linkgie.galaxyframework.httpproxy.ResponseHandler;
import com.linkgie.galaxyframework.httpproxy.ServiceInvocationContext;
import com.linkgie.galaxyframework.httpproxy.ServiceRequest;
import com.linkgie.galaxyframework.httpproxy.ServiceResponse;

/**
 * 默认的 HTTP 错误码的响应处理器；
 * <p>
 * 当 HTTP 状态码处于重定向范围（ >= 300 且 < 400 ）时，抛出 HttpRedirectException 异常；
 * 当 HTTP 状态码处于重定向范围（ >= 400 ）时，抛出 HttpStatusException 异常；
 * <p>
 * 如果回复是正常的，则抛出 UnsupportedOperationException 异常；
 * <p>
 * 
 * @author haiq
 *
 */
public class HttpErrorResponseHandler implements ResponseHandler {

    public static final HttpErrorResponseHandler INSTANCE = new HttpErrorResponseHandler();

    private HttpErrorResponseHandler() {
    }

    @Override
    public Object handleResponse(ServiceRequest request, ServiceResponse response,
            ServiceInvocationContext invocationContext) throws Exception {
        // 引发 http 异常；
        // 300 - 399 : 重定向消息；
        // 400 - 499 : 客户端错误响应；
        // 500 - 599 : 服务端错误响应；
        if (response.getHttpStatusCode() >= 400) {
            processAndThrowHttpException(invocationContext, request, response);
            // 注：实际不会执行到此，因为上一步已抛出异常；
            return null;
        }
        // 处理重定向；
        if (response.getHttpStatusCode() >= 300) {
            processAndThrowRedirectException(invocationContext, request, response);
            // 注：实际不会执行到此，因为上一步已抛出异常；
            return null;
        }
        // 不处理正常的响应，抛出异常；
        throw new UnsupportedOperationException("Unsupported processing of http response with success status code: "
                + response.getHttpStatusCode());
    }

    /**
     * 处理 HTTP 错误响应(状态码 >= 400），并抛出 HttpStatusException 异常；
     * 
     * @param actionContext
     * @param response
     */
    public static void processAndThrowHttpException(ServiceInvocationContext actionContext, ServiceRequest request,
            ServiceResponse response) throws HttpStatusException {
        String content = readResponseContent(request, response, actionContext);
        String errMsg = String.format("[http-status=%s][%s] %s", response.getHttpStatusCode(),
                response.getHttpStatusMessage(), content);
        throw new HttpStatusException(response.getHttpStatusCode(), response.getHttpStatusMessage(), errMsg);
    }

    public static String readResponseContent(ServiceRequest request, ServiceResponse response,
            ServiceInvocationContext actionContext) {
        String content = null;
        if (actionContext.isResolveContentOnHttpError()) {
            try {
                content = (String) StringResponseHandler.INSTANCE.handleResponse(request, response,
                        actionContext);
            } catch (HttpRequestException e) {
                throw e;
            } catch (Exception e) {
                throw new HttpRequestException(e.getMessage(), e);
            }
        }
        return content;
    }

    /**
     * 处理 HTTP 300 ~ 399 重定向消息，并抛出 HttpRedirectException 异常；
     * 
     * @param actionContext
     * @param response
     */
    public static void processAndThrowRedirectException(ServiceInvocationContext actionContext, ServiceRequest request,
            ServiceResponse response) throws HttpRedirectException {
        String errMsg = String.format("Redirect [status=%s]", response.getHttpStatusCode());
        throw new HttpRedirectException(response.getHttpStatusCode(), response.getHttpStatusMessage(), errMsg);
    }
}
